#ifndef __Q__DYN__STORE__HH__
#define __Q__DYN__STORE__HH__

#include <vector>
#include <iostream>
#include <string>
#include "WeakPtr.h"

template<typename ItemType>		class QDynHolder;

template<typename ItemType>
class QDynHolder : public WeakPtr<ItemType>
{
public:
	QDynHolder( Item * ptr = NULL, bool destroy = false ) : WeakPtr( ptr, destroy){}
	QDynHolder( const QDynHolder<ItemType>& hdr ) : WeakPtr(hdr){}
	~QDynHolder(){ destroy(); }
};

template< typename ItemType, typename ContainerType >
class QDynStore
{
public:
	typename typedef QDynHolder<ItemType>				Holder;
	typename typedef ItemType							Item;
	typename typedef ContainerType						Container;
	typename typedef Container::iterator				Iterator;
	typename typedef Container::const_iterator			ConstIterator;
	typename typedef Container::reverse_iterator		ReverseIterator;
	typename typedef Container::const_reverse_iterator	ReverseConstIterator;
protected:
	Container mStore;
	
private:
	Holder _NullRet;

public:
	QDynStore( ){}
	QDynStore( const QDynStore< Holder, Container > & rk ) : mStore( rk.mStore ){}
	~QDynStore( ){ destroy(); }
	
	Holder& invalidReturn(){ return _NullRet; }
	const Holder& invalidReturn() const{ return _NullRet; }

	Iterator begin(){ return mStore.begin(); }
	Iterator end(){ return mStore.end(); }

	ConstIterator begin() const{ return mStore.begin(); }
	ConstIterator end() const{ return mStore.end(); }
	
	ReverseIterator rbegin(){ return mStore.rbegin(); }
	ReverseIterator rend(){ return mStore.rend(); }

	ReverseConstIterator rbegin() const{ return mStore.rbegin(); }
	ReverseConstIterator rend() const{ return mStore.rend(); }

	QDynStore& operator = ( const QDynStore< Holder, ContainerType > & rk ){ mStore = rk.mStore; return *this; }

	Holder store( Item * item, bool destroy_ = true ){ 
		Holder h( item ); 
		mStore.push_back( h ); 
		h.setDestroy(false); 
		mStore[mStore.size()-1].setDestroy(destroy_); 
		return h; 
	}
	Holder lastStored() const{ if(mStore.empty()) return Holder(); return mStore.back(); }

	const Holder& retrieve( const size_t id ) const
	{
		if( id < mStore.size() ) return mStore.at(id);
		return _NullRet;
	}
	Holder& retrieve( const size_t id )
	{
		if( id < mStore.size() ) return mStore.at(id);
		return _NullRet;
	}
	const Holder& retrieve( const Holder& h ) const
	{
		for( auto i=mStore.begin(); i!=mStore.end(); i++ )
		{
			if( *i == h ) return *i;
		}
		return _NullRet;
	}
	Holder& retrieve( const Holder& h )
	{
		for( auto i=mStore.begin(); i!=mStore.end(); i++ )
		{
			if( *i == h ) return *i;
		}
		return _NullRet;
	}
	bool empty() const{ return mStore.empty(); }
	size_t size() const{ return mStore.size(); }
	size_t count() const{ return mStore.size(); }
	size_t indexOf( const Holder& h )
	{
		size_t id = 0;
		for( auto i=mStore.begin(); i!=mStore.end(); i++ )
		{
			if( *i == h ) return id;
			id++;
		}
		return id;
	}
	bool isStored( const Holder& h ) const
	{
		for( auto i=mStore.begin(); i!=mStore.end(); i++ )
		{
			if( *i == h ) return true;
		}
		return false;
	}
	void remove( Holder& h )
	{
		if( !isStored( h ) ) return ;
		for( auto i=mStore.begin(); i!=mStore.end(); i++ )
		{
			if( *i == h ){
				mStore.erase( i );
			}
		}
		if( h ) h.destroy();
	}

	void destroy(){ for( auto i=mStore.begin(); i!=mStore.end(); i++ ) i->destroy(); mStore.clear(); }
};

#endif